package fctuc.dei.myTwitter.client;

import static fctuc.dei.myTwitter.constants.MyTwitterConstants.MAX_ATTEMPTS;
import static fctuc.dei.myTwitter.constants.MyTwitterConstants.SERVER_FILES;
import static fctuc.dei.myTwitter.constants.MyTwitterConstants.RMI_LISTENER_PORT;
import static fctuc.dei.myTwitter.constants.MyTwitterConstants.sleep;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.channels.SelectionKey;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;

import fctuc.dei.myTwitter.com.Message;
import fctuc.dei.myTwitter.com.RMIServer;
import fctuc.dei.myTwitter.com.RMIServerConnection;

public class RMIConnection extends ServerConnection {
    private Object mutex = new Object();
    private RMIServer rmiServer;
    private RMIServerConnection rmiConnection;
    private RMIClientListenerImpl rmiClientListenerImpl;

    public RMIConnection(MyTwitterClient c) {
        super(c);
        try {
            rmiClientListenerImpl = new RMIClientListenerImpl(c, this);
        } catch(RemoteException e) {
            System.err.println("Remote Exception: %s\n" + e);
        }
        connect();
    }
    
    public void realConnect() {
        System.getProperties().put("java.security.policy", SERVER_FILES + "/policy.all");
        System.setSecurityManager(new RMISecurityManager());
        
        for (int i = 0; i < MAX_ATTEMPTS; i++) {
            boolean success = false;
            
            try{
                if (connected) {
                    success = true;
                    return;
                }

                if (disconnect)
                    return;
 
                rmiServer = (RMIServer) Naming.lookup("rmi://" + client.host + ":"
                                                      + RMI_LISTENER_PORT + "/MyTwitterServer"); 
                rmiConnection = this.rmiServer.connect(rmiClientListenerImpl); 
                success = true;
                connected = true; 
                return;
 
            } catch (NotBoundException e) {
                System.err.println("NotBoundException:" + e.getMessage() + "\n");
            } catch (MalformedURLException eURL) {
            	System.err.println("MalformedURLException:"+ eURL.getMessage() + "\n");
            } catch(RemoteException eR) {
            	System.err.println("RemoteException:" + eR.getMessage() + "\n");
            } finally {
                if (disconnect)
                    return;
                else if (!success) {
                	System.err.println("Connection error: Next attempt in 2 seconds...\n");
                    connected = false;
                    sleep(2000);
                } else {
                	System.err.println("Connection Established.\n");
                }
            }
        }
        this.client.com.write("Connection failed.");
        terminate();
        return;
    }

    public boolean realSend(Message m) {
        try {
            if (!connected)
                return false;
            rmiConnection.handleMessage(m);
        } catch (IOException ioe) {
            System.err.println("!!! [RMI] Error during write process: %s\n" + ioe);
            connect();
            return false;
        } 
        return true;
    }

    public void realTerminate() {
        connected = false;
        disconnect = true;
    }

	@Override
	public void noConnectionWarning() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean realSend(Message m, SelectionKey key) {
		// TODO Auto-generated method stub
		return false;
	}
}

